using System;

namespace ntools.NetduinoGo.PlusModule.NetduinoGo.Framework
{
    public class FileStream : System.IO.Stream
    {

        private byte instance;

        public FileStream(string path, System.IO.FileMode mode)
        {
            byte[] buffer = new byte[path.Length + 1];
            buffer[0] = (byte)(int)mode;

            Array.Copy(System.Text.Encoding.UTF8.GetBytes(path), 0, buffer, 1, path.Length);

            this.instance = Plus.Link.Call(Link.INSTANCE_MAIN, Link.COMMAND_MAIN_CREATEFILESTREAM, buffer)[0];
        }

        public override bool CanRead
        {
            get { return (Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_CANREAD, new byte[] { this.instance })[0] == 1); }
        }

        public override bool CanSeek
        {
            get { return (Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_CANSEEK, new byte[] { this.instance })[0] == 1); }
        }

        public override bool CanWrite
        {
            get { return (Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_CANWRITE, new byte[] { this.instance })[0] == 1); }
        }

        public override void Flush()
        {
            Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_FLUSH, new byte[] { this.instance });
        }

        public override long Length
        {
            get { return Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_LENGTH, new byte[] { this.instance })[0]; }
        }

        public override long Position
        {
            get
            {
                return Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_POSITION, new byte[] { this.instance })[0];
            }
            set
            {
                Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_POSITION, new byte[] { this.instance, (byte)value });
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            byte[] read = Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_READ, new byte[] { this.instance, (byte)count });

            Array.Copy(read, 0, buffer, offset, read.Length);

            return read.Length;
        }

        public override long Seek(long offset, System.IO.SeekOrigin origin)
        {
            return Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_SEEK, new byte[] { this.instance, (byte)offset, (byte)origin })[0];
        }

        public override void SetLength(long value)
        {
            Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_SETLENGTH, new byte[] { this.instance, (byte)value });
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            byte[] parameters = new byte[buffer.Length + 3];

            parameters[0] = this.instance;
            parameters[1] = (byte)offset;
            parameters[2] = (byte)count;

            Array.Copy(buffer, 0, parameters, 3, buffer.Length);

            Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_WRITE, parameters);
        }

        public void Dispose()
        {
            Plus.Link.Call(Link.INSTANCE_FILESTREAM, Link.COMMAND_FILESTREAM_DISPOSE, new byte[] { this.instance });
        }
    }
}
